﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Caliburn.Micro;
using GTServices.Model;
using GTServices.Entities;
using System.Collections.ObjectModel;
using GTServices.WPF.Client.ViewModels.Entities;
using GTServices.WPF.Client.Data;
using System.Windows;
using GTServices.Model.CoRoutine;

namespace GTServices.WPF.Client.ViewModels
{
    public class GTSearchDialogViewModel : Screen
    {
        private string _searchPattern;
        public string SearchPattern
        {
            get { return _searchPattern; }
            set { _searchPattern = value; NotifyOfPropertyChange(() => SearchPattern); }
        }
        public string Status { get; set; }

        private string _path;

        public string Path
        {
            get { return _path; }
            set
            {
                _path = value;
                NotifyOfPropertyChange(() => Path); 
            }
        } 

        private string _extensionsString;
        public string ExtensionsString
        {
            get { return _extensionsString; }
            set { _extensionsString = value; NotifyOfPropertyChange(() => ExtensionsString); }
        }

        //Not supposed to bind to this. 
        public List<FileExtension> Extensions { get; set; } 
        
        private Language _Language;
        public Language Language
        {
            get { return _Language; }
            set { 
                
                _Language = value; 
                NotifyOfPropertyChange(() => Language);
            }
        }
        public List<Language> Languages { get { return GTApplication.Instance.DataModel.Languages.Where(x=> !x.Name.Equals("All")).ToList(); } }

        private bool _byExtension;
        public bool ByExtension
        {
            get { return _byExtension; }
            set { _byExtension = value; NotifyOfPropertyChange(() => ByExtension); }
        }


        public bool IsRunning { get; set; } 

        public GrepResultsTreeViewModel GrepResultsTreeView { get; set; }
        public bool IncludeInResults { get; set; } 
        private BindableCollection<GrepResult> _results; 

        public GTSearchDialogViewModel()
        {
            ByExtension = true;
            _results = new BindableCollection<GrepResult>();
            GrepResultsTreeView = new GrepResultsTreeViewModel(new SyncedBindableCollection<GrepResult, GrepResultTreeViewItemViewModel>(_results,
                                                                                                     (x) => new GrepResultTreeViewItemViewModel() { GrepResult = x,
                                                                                                                                                    Parent = GrepResultsTreeView},
                                                                                                     (m, vm) => vm.GrepResult.Equals(m)));
            
            this.Extensions = new List<FileExtension>();
            this.ExtensionsString = "*.*";
            this.IncludeInResults = true; 

            this.DisplayName = "Search";
            NotifyOfPropertyChange(() => GrepResultsTreeView);
            NotifyOfPropertyChange(() => DisplayName);
            NotifyOfPropertyChange(() => IncludeInResults); 
        }

        public void Find(){
            if (IsRunning)
            {
                MessageBox.Show("Already Running"); 
            }
            if (String.IsNullOrWhiteSpace(Path))
            {
                MessageBox.Show("Null or Empty Path");
                return;
            }
            if (!System.IO.Directory.Exists(Path))
            {
                MessageBox.Show("Path does not exist");
                return;
            }
            if (!string.IsNullOrEmpty(this.SearchPattern))
            {
                this.Status = "Running..";
                NotifyOfPropertyChange(() => Status);

                if (ByExtension)
                {
                    Extensions = GetFileExtensionsFromString(this.ExtensionsString);
                }
          

                List<Pattern> patterns = new List<Pattern>();
                patterns.Add(new Pattern() { PatternStr = SearchPattern });

                List<Language> languages = new List<GTServices.Entities.Language>();
                GrepRequest gr = null;
                if (this.Language != null)
                {
                    languages.Add(this.Language);
                    gr = GTApplication.Instance.GrepModel.GetGrepRequest(Path, patterns, languages, null, null);
                }
                else
                {
                    gr = GTApplication.Instance.GrepModel.GetGrepRequest(Path, patterns, null, null, Extensions);
                }

                ExecuteDirectoryGrepRequestRoutine routine = new ExecuteDirectoryGrepRequestRoutine(gr);
                routine.OnNextDirectory += new ExecuteDirectoryGrepRequestRoutine.NextDirectory((x, y) =>
                {
                    this.Status = x;
                    NotifyOfPropertyChange(() => Status);
                });
                /*
                    ExecuteGrepRequestRoutine routine = new ExecuteGrepRequestRoutine(gr);
                    */
                routine.Completed += (x, y) =>
                {
                    if (y.Error == null)
                    {
                        if(this.IncludeInResults)
                            GTApplication.Instance.DataModel.GrepResults.Add(routine.Result);

                        this._results.Add(routine.Result); 

                        this.Status = "Completed";
                    }
                    else
                    {
                        this.Status = "Errored.." + y.Error.Message;
                    }
                    NotifyOfPropertyChange(() => Status);
                    IsRunning = false;
                };

                Dispatcher.Instance.QueueItem(routine); 
            }
            else
            {
                MessageBox.Show("No Extensions selected or faield to parse the extension string"); 
            }
        }


        public void PickDir()
        {
            System.Windows.Forms.FolderBrowserDialog fbd = new System.Windows.Forms.FolderBrowserDialog();

            if (System.IO.Directory.Exists(this.Path))
                fbd.SelectedPath = this.Path;

            if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                this.Path = fbd.SelectedPath;

                NotifyOfPropertyChange(() => Path);
            }
        }

        public List<FileExtension> GetFileExtensionsFromString(String s)
        {

            List<FileExtension> exts = new List<FileExtension>(); 
            string[] parts = s.Split(',');
            foreach (string part in parts)
            {
                var trimPart = part.Trim();
                if (trimPart[0] == '*' && trimPart[1] == '.')
                {
                    string tPart = trimPart.Substring(1); //Remove the leading *
                    FileExtension fe = GTApplication.Instance.DataModel.FileExtensions.ToList().FirstOrDefault((x) => x.Extension.Equals(tPart, StringComparison.OrdinalIgnoreCase));
                    if (fe != null)
                    {
                        exts.Add(fe); 
                    }
                }
                else
                {
                        //TODO: Log/Exception
                }
            }
            return exts;
        }
        public void Save(){
            //Put the results in the GrepResult collection. 


        }
    }
}
